#pragma once
#include<queue>
#include"sem.hpp"
#include"mutex.hpp"

namespace ringbufmodule
{
    template<class T>
    class ringbuf
    {
    public:
        ringbuf(int cap):buf(cap),_cap(cap),c_step(0),p_step(0),space_sem(_cap),data_sem(0)
        {}
        void Pop(T* data){
            data_sem.q();
            {
                mutexmodule::lockgroud lock(c_mutex);
                *data=buf[c_step];
                c_step++;
                c_step%=_cap;
            }
            space_sem.v();
        }
        void Equeue(const T&data){
            space_sem.q();
            {
                mutexmodule::lockgroud lock(p_mutex);
                buf[p_step]=data;
                p_step++;
                p_step%=_cap;
            }
            data_sem.v();
        }
        ~ringbuf()
        {}
    private:
        std::vector<T> buf;
        int _cap;
        semmodule::Sem space_sem;//空间信号
        semmodule::Sem data_sem;//数据信号量
        int c_step;
        int p_step;
        mutexmodule::mutex p_mutex;//生产者之间的互斥锁
        mutexmodule::mutex c_mutex;//消费者之间的互斥锁
    };
}